Option Explicit On
Option Strict On

Imports System.Collections
Imports System.Collections.Generic
Imports nstl
Imports NUnit.Framework
Imports NStl.SyntaxHelper


Namespace nstl.test
    <TestFixture()> _
    Public Class mulitset
        ''' <summary>
        ''' Initialize() is called once during test execution before
        ''' test methods in this test class are executed.
        ''' </summary>
        <SetUp()> Public Sub Initialize()
        End Sub


        ''' <summary>
        ''' Cleanup() is called once during test execution after
        ''' test methods in this class have executed unless the
        ''' corresponding Initialize() call threw an exception.
        ''' </summary>
        <TearDown()> _
        Public Sub Cleanup()
        End Sub

        <Test()> _
    Public Sub customComparison()
            'Test the set with different comparison functors

            'less
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            '10, 10, 20, 20, 30, 30, 40, 50
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 10, 20, 20, 30, 30, 40, 50}))

            'greater
            s = New MultiSet(Of Integer)(Compare.Greater(Of Integer)())
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            '50, 40, 30, 30, 20, 20, 10, 10
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {50, 40, 30, 30, 20, 20, 10, 10}))

        End Sub

        <Test()> _
        Public Sub insert2()

            'insert an object--------------
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())

            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
                s.Insert(i)
            Next
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}))


            s = New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            Dim v As New List(Of Integer)
            For i As Integer = 9 To 0 Step -1
                v.Add(i)
                v.Add(i)
            Next

            Algorithm.RandomShuffle(v.Begin, v.End)
            For i As Integer = v.Count() - 1 To 0 Step -1
                s.Insert(v(i))
            Next
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}))


            'object at position
            s = New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
                s.Insert(i)
            Next
            s.Insert(s.Begin(), 0)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}))
            s.Insert(s.Begin(), 10)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10}))

            'range
            s = New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            v = New List(Of Integer)
            For i As Integer = 9 To 0 Step -1
                v.Add(i)
                v.Add(i)
            Next
            Algorithm.RandomShuffle(v.Begin, v.End)
            s.Insert(v.Begin(), v.End())
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}))
        End Sub

        <Test()> _
        Public Sub clear()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())

            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            s.Clear()
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {}))
        End Sub

        <Test()> _
        Public Sub count()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
                s.Insert(i)
            Next

            Assert.IsTrue(s.CountOf(2) = 2)
            Assert.IsFalse(s.CountOf(11) = 1)
            Assert.IsTrue(s.CountOf(11) = 0)
        End Sub

        <Test()> _
        Public Sub empty()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
                s.Insert(i)
            Next

            Assert.IsFalse(s.Empty())
            s.Clear()
            Assert.IsTrue(s.Empty())
        End Sub

        <Test()> _
        Public Sub equal_range()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
                s.Insert(i)
            Next

            Dim ret As Range(Of Integer, MultiSet(Of Integer).Iterator) = _
                s.EqualRange(5)
            Dim v As New List(Of Integer)(ret)

            Assert.IsFalse(TestUtil.mismatch(v, New List(Of Integer)(New Integer() {5, 5})))
        End Sub

        <Test()> _
        Public Sub [erase]()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)

            'set should contain 10, 10, 20, 30

            'erase at position
            Dim pos As MultiSet(Of Integer).Iterator = CType(s.Begin().Add(2), Global.NStl.Collections.MultiSet(Of Integer).Iterator)
            Assert.IsTrue(DirectCast(pos.Value, Integer) = 20)
            s.Erase(pos)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 10, 30}))

            'erase a range
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 10, 20, 30, 30, 40, 50}))
            '                                        0,  1,  2,  3,  4,  5,  6
            pos = CType(s.Begin().Add(1), Global.NStl.Collections.MultiSet(Of Integer).Iterator)
            Assert.IsTrue(DirectCast(pos.Value, Integer) = 10)
            Dim pos2 As MultiSet(Of Integer).Iterator = CType(s.Begin().Add(3), Global.NStl.Collections.MultiSet(Of Integer).Iterator)
            Assert.IsTrue(DirectCast(pos2.Value, Integer) = 30)
            s.Erase(pos, pos2)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 30, 30, 40, 50}))

            'erase a value
            Dim count As Integer = s.Erase(40)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 30, 30, 50}))
            Assert.IsTrue(count = 1)
            count = s.Erase(100)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 30, 30, 50}))
            Assert.IsTrue(count = 0)
        End Sub

        <Test()> _
        Public Sub find()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            s.Insert(10)
            s.Insert(30)
            s.Insert(20)
            s.Insert(10)
            s.Insert(20)
            s.Insert(40)
            s.Insert(30)
            s.Insert(50)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {10, 10, 20, 20, 30, 30, 40, 50}))

            Dim pos As MultiSet(Of Integer).Iterator = s.Find(30)
            Assert.IsTrue(DirectCast(pos.Value, Integer) = 30)
            Assert.IsTrue(s.Begin().DistanceTo(pos) = 4)
            Assert.IsTrue(Not pos.Equals(s.End()))

            pos = s.Find(42)
            Assert.IsTrue(pos.Equals(s.End()))
        End Sub
        <Test()> _
        Public Sub insert()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())

            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))


            s = New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            Dim v As New List(Of Integer)
            For i As Integer = 9 To 0 Step -1
                v.Add(i)
            Next

            Algorithm.RandomShuffle(v.Begin, v.End)
            For i As Integer = 9 To 0 Step -1
                s.Insert(v(i))
            Next
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))


            s = New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            s.Insert(s.Begin(), 0)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}))
            s.Insert(s.Begin(), 10)
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))

            s.Insert(v.Begin(), v.End())
            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10}))
        End Sub

        <Test()> _
        Public Sub lower_upper_bound()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            s.Insert(3)
            s.Insert(3)
            s.Insert(3)
            s.Insert(3)

            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9}))

            Dim low As MultiSet(Of Integer).Iterator = s.LowerBound(3)
            Dim up As MultiSet(Of Integer).Iterator = s.UpperBound(3)

            Dim v As New List(Of Integer)(low.AsEnumerable(up))
            Assert.IsFalse(TestUtil.mismatch(v, New List(Of Integer)(New Integer() {3, 3, 3, 3, 3})))
        End Sub

        <Test()> _
        Public Sub equal_range2()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            s.Insert(3)
            s.Insert(3)
            s.Insert(3)
            s.Insert(3)

            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 1, 2, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9}))

            Dim its As Range(Of Integer, MultiSet(Of Integer).Iterator) = s.EqualRange(3)
            Dim v As New List(Of Integer)(its)
            Assert.IsFalse(TestUtil.mismatch(v, New List(Of Integer)(New Integer() {3, 3, 3, 3, 3})))
        End Sub

        <Test()> _
        Public Sub size()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            For i As Integer = 9 To 0 Step -1
                s.Insert(i)
            Next
            s.Insert(3)
            s.Insert(3)
            s.Insert(3)
            s.Insert(3)
            Assert.IsTrue(s.Count = 14)
        End Sub

        <Test()> _
        Public Sub swap()
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            s.Insert(10)
            s.Insert(20)
            s.Insert(30)
            s.Insert(40)
            s.Insert(50)

            '10, 20, 30, 40, 50

            Dim s2 As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            s2.Insert(80)
            s2.Insert(70)
            s2.Insert(60)
            s2.Insert(50)

            s.Swap(s2)

            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {50, 60, 70, 80}))
            Assert.IsFalse(TestUtil.mismatch(s2, New Integer() {10, 20, 30, 40, 50}))
        End Sub


        <Test()> _
        Public Sub TestIInsertableImp()
            Dim m As New MultiMap(Of Integer, String)(Compare.Less(Of Integer))
            For i As Integer = 0 To 9
                m.Insert(i, i.ToString())
                m.Insert(i, i.ToString() + "_2")
            Next
            Dim s As New MultiSet(Of Integer)(Compare.Less(Of Integer)())
            Algorithm.Transform(m.Begin, m.End, s.InsertIterator(s.Begin()), [Select].FirstFromKeyValuePair(Of Integer, String)())

            Assert.IsFalse(TestUtil.mismatch(s, New Integer() {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}))

        End Sub

    End Class


End Namespace


